#include "StdAfx.h"
#include "VertexLayout.h"

namespace rkt
{
	extern GLuint getAttrLocation(unsigned int usage,unsigned int index);
	extern bool getAttrGLInfo(VertexElementType type,GLenum&  glType,GLint& components,GLboolean& normalized);

	IVertexLayout* VertexLayout::create()
	{
		return new VertexLayout;
	}

	void VertexLayout::release()
	{
		delete this;
	}

	VertexLayout::VertexLayout()
		:m_VertexDataSize(0)
	{

	}

	VertexLayout::~VertexLayout()
	{

	}
	
	bool VertexLayout::reset(const VertexElementDecs* pElements,unsigned int elementsCount)
	{
		m_VertexDataSize = 0;
		m_VertexAttrs.clear();

		if(!pElements) return false;

		for (unsigned int i = 0; i < elementsCount; i++)
		{
			m_VertexDataSize += g_vtext_size[pElements[i].type];
			pushVertexAttr(pElements[i]);
		}
		return true;
	}

	void VertexLayout::push(const VertexElementDecs& element)
	{
		m_VertexDataSize += g_vtext_size[element.type];
		pushVertexAttr(element);
	}

	void VertexLayout::begin(void* pdata)
	{
		for (unsigned int i = 0; i < m_VertexAttrs.size(); i++)
		{
			glEnableVertexAttribArray(m_VertexAttrs[i].loacation);
			glVertexAttribPointer(m_VertexAttrs[i].loacation
				, m_VertexAttrs[i].components
				, m_VertexAttrs[i].type
				, m_VertexAttrs[i].normalized
				, getVertexDataSize()
				, (const void*)((char*)pdata + m_VertexAttrs[i].offset)
				);
			TestGLError("HighLevelShaderProgram::bind");
		}
	}

	void VertexLayout::end()
	{
		for(unsigned int i=0;i<m_VertexAttrs.size();i++)
		{
			glDisableVertexAttribArray(m_VertexAttrs[i].loacation);
			TestGLError("HighLevelShaderProgram::unbind");
		}
	}
	
	void VertexLayout::pushVertexAttr(const VertexElementDecs& element)
	{
		VertexAttr va;
		va.offset = element.offset;
		va.loacation = getAttrLocation(element.usage, element.usageIndex);
		
		getAttrGLInfo(element.type,va.type,va.components,va.normalized);

		m_VertexAttrs.push_back(va);
	}
	
}